在上一篇,我們已經完成了 Vitest 的初始化,並撰寫了第一個單元測試。但光有測試檔還不夠,我們也要透過覆蓋率來檢視測試是否完整,避免有些功能被遺漏沒檢查到。
本篇將會延續上一篇的基礎,帶你進一步加入測試覆蓋率,並撰寫一個簡單的整合測試,讓驗收過程更全面😀。
本篇重點整理:
在寫測試的時候,我們常常會有一個疑問:
到底我的測試有沒有把程式的所有情況都跑過❓
這時候就需要測試覆蓋率 ( Test Coverage ),就是到底測試覆蓋了多少程式碼。
這能幫助我們發現:
當我們用 Vitest 跑覆蓋率時,通常會看到這幾個指標:
覆蓋率只是參考指標,不是唯一標準。100% 覆蓋率 ≠ 沒有 bug,因為測試可能只覆蓋程式碼而沒驗證正確性。實務上大部分專案會設定 70% ~ 90% 作為目標。
vitest.config.ts
裡可以限制測試覆蓋率,例如:coverage: {
lines: 80,
functions: 80,
branches: 70,
statements: 80,
}
這樣如果覆蓋率低於標準,測試就會失敗。
一樣,先安裝 Vitest Coverage 套件:
npm i -D @vitest/coverage-v8
在 vitest.config.ts
裡加上 coverage 設定:
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
{/* ... */}
coverage: {
provider: "v8", // 使用 v8 引擎 (官方推薦)
reporter: ["text", "json", "html"],
reportsDirectory: "./coverage", // 輸出到 coverage 資料夾
},
},
});
在 package.json
加一個 script:
"scripts": {
"test": "vitest",
"coverage": "vitest run --coverage"
}
執行測試
npm run coverage
接著可以看到終端機與檔案裡會顯示 coverage 的結果了👍。
在 上一篇 有介紹到整合測試,這裡就不多做贅述,這裡再提供更進階一點的範例,這些會是整合測試經常會遇到的程式碼:
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { vi } from "vitest";
import LoginForm from "../LoginForm";
describe("LoginForm 整合測試", () => {
it("使用者輸入帳密並送出後,應該呼叫 onSubmit", async () => {
const mockSubmit = vi.fn(); // 建立假的函式來監控是否有被呼叫
render(<LoginForm onSubmit={mockSubmit} />);
// 模擬使用者輸入帳號與密碼
await userEvent.type(screen.getByLabelText(/帳號/i), "testUser");
await userEvent.type(screen.getByLabelText(/密碼/i), "123456");
// 模擬按下送出按鈕
await userEvent.click(screen.getByRole("button", { name: /登入/i }));
// 驗證 submit 是否被呼叫,且帶入正確參數
expect(mockSubmit).toHaveBeenCalledWith({
username: "testUser",
password: "123456",
});
});
});
render
:把 React 元件渲染在測試環境裡,就像真的放到瀏覽器一樣,方便後續操作。screen
:提供一個「查詢 DOM 的全域物件」,常用 getByText
、getByRole
、getByLabelText
來找到畫面元素。userEvent
:模擬使用者操作(輸入文字、點擊、鍵盤操作),比 fireEvent
更接近真實使用情境。vi
:來自 Vitest,負責建立 mock 函式或模擬外部依賴,在測試中能精確監控呼叫次數、參數內容。